package com.fpc.cn.springbootutil.annotation.paramTrim;

import com.fpc.cn.springbootutil.exception.BusinessException;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.stereotype.Component;

import java.beans.BeanInfo;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.math.BigDecimal;
import java.util.Collection;
import java.util.Date;
import java.util.LinkedHashMap;
import java.util.Map;

/**
 * @date 2025/4/29
 * @author fupengcheng
 * @describe  对所有String 类型的字符串 去除两边空格, 支持空校验,长度校验
 */
@Slf4j
@Aspect
@Component
public class TrimRequestParamsAspect {

    // 最大递归深度（初始剩余次数）
    private static final int MAX_RECURSION_DEPTH = 5;

    @Before("@annotation(trimRequestParams)")
    public void before(JoinPoint joinPoint, TrimRequestParams trimRequestParams) {
        boolean enableNotNullCheck = trimRequestParams.notNullCheck();
        boolean enableLengthCheck = trimRequestParams.lengthCheck();
        Object[] args = joinPoint.getArgs();
        if (args != null) {
            for (Object arg : args) {
                if (arg != null) {
                    try {
                        // 初始调用时传递 MAX_RECURSION_DEPTH 作为剩余次数
                        processArg(arg, enableNotNullCheck, enableLengthCheck, MAX_RECURSION_DEPTH);
                    } catch (IllegalAccessException e) {
                        log.error("处理参数时发生异常", e);
                    }
                }
            }
        }
    }

    /**
     * @date 2025/4/29
     * @author fupengcheng
     * @describe 参数判断
     */
    private void processArg(Object arg, boolean enableNotNullCheck, boolean enableLengthCheck, int remainingCount) throws IllegalAccessException {
        // 递归终止条件：剩余次数 ≤ 0 时停止
        if (remainingCount <= 0) {
        //    log.info("=======>>>>> 递归终止（剩余次数: {}）<<<<<========", remainingCount);
            return;
        }
     //   log.info("=======>>>>> 递归层级: {}（剩余次数: {}） <<<<<========",MAX_RECURSION_DEPTH - remainingCount + 1, remainingCount);


        if (arg instanceof String) {
           // arg = ((String) arg).trim();
            if (((String) arg).contains("{")) {
               // log.info("=======>>>>> 跳过 String 对象去空格处理 <<<<<========");
            }
        }  else if (arg instanceof Integer || arg instanceof Long || arg instanceof Double || arg instanceof Boolean || arg instanceof Date || arg instanceof Byte
                || arg instanceof Short || arg instanceof Float || arg instanceof Character || arg instanceof BigDecimal) {
            return;
        } else if (arg instanceof Collection) {
            processCollection((Collection<?>) arg, enableNotNullCheck, enableLengthCheck, remainingCount);
        } else if (arg instanceof Map || arg instanceof LinkedHashMap) {
            processMap((Map<Object, Object>) arg, enableNotNullCheck, enableLengthCheck, remainingCount);
        } else if (isJavaBean(arg.getClass())) {
           // log.info("=======>>>>> 处理 Java Bean <<<<<========");
            processClassObj(arg, enableNotNullCheck, enableLengthCheck, remainingCount);
        }/*else{  fpc 此处千万不要启动,避免不知道的数据类型,进行递归死循环
            processObject(arg, enableNotNullCheck, enableLengthCheck,  remainingCount);
        }*/
    }

    /**
     * @date 2025/4/29
     * @author fupengcheng
     * @describe 处理集合类型参数
     */
    private void processCollection(Collection<?> collection, boolean enableNotNullCheck, boolean enableLengthCheck, int remainingCount) throws IllegalAccessException {
        // 提前检查剩余次数，避免无效遍历
        if (remainingCount <= 0) {
            return;
        }
        for (Object item : collection) {
            if (item != null) {
                // 传递剩余次数 - 1
                processArg(item, enableNotNullCheck, enableLengthCheck, remainingCount - 1);
            }
        }
    }
    /**
     * @date 2025/4/29
     * @author fupengcheng
     * @describe 处理javaBean类型参数
     */
    private void processClassObj(Object obj, boolean enableNotNullCheck, boolean enableLengthCheck, int remainingCount) throws IllegalAccessException {
        if (obj == null || remainingCount <= 0) {
            return;
        }
        Class<?> clazz = obj.getClass();
        Field[] fields = clazz.getDeclaredFields();
        for (Field field : fields) {
            field.setAccessible(true);
            Object value = field.get(obj);
            ParamCheck paramCheck = field.getAnnotation(ParamCheck.class);
            if (value != null) {
                // 传递剩余次数 - 1
                processArg(value, enableNotNullCheck, enableLengthCheck, remainingCount - 1);
                if (value instanceof String) {
                    field.set(obj, ((String) value).trim());
                    value = ((String) value).trim();
                }
            }
            checkString(value==null?"":String.valueOf(value), paramCheck, enableNotNullCheck, enableLengthCheck);
        }
    }

    /**
     *  fpc  参数类型未知的时候不要使用该方法
     * @param obj
     * @param enableNotNullCheck
     * @param enableLengthCheck
     * @param remainingCount
     * @throws IllegalAccessException
     */
    private void processObject(Object obj, boolean enableNotNullCheck, boolean enableLengthCheck, int remainingCount) throws IllegalAccessException {
        if (obj == null || remainingCount <= 0) {
            return;
        }
        Class<?> clazz = obj.getClass();
        Field[] fields = clazz.getDeclaredFields();
        for (Field field : fields) {
            field.setAccessible(true);
            Object value = field.get(obj);
            if (value != null) {
                if (value instanceof String) {
                    field.set(obj, ((String) value).trim());
                }
                // 传递剩余次数 - 1
                processArg(value, enableNotNullCheck, enableLengthCheck, remainingCount - 1);
            }
        }
    }

    private void processMap(Map<Object, Object> map, boolean enableNotNullCheck, boolean enableLengthCheck, int remainingCount) throws IllegalAccessException {
        if (remainingCount <= 0) {
            return;
        }
        for (Map.Entry<Object, Object> entry : map.entrySet()) {
            Object value = entry.getValue();
            if (value != null) {
                if (value instanceof String) {
                    String fds = ((String) value).trim();
                    entry.setValue(fds);
                }
                // 传递剩余次数 - 1
                processArg(value, enableNotNullCheck, enableLengthCheck, remainingCount - 1);
            }
        }
    }

    private void checkString(String value, ParamCheck paramCheck, boolean enableNotNullCheck, boolean enableLengthCheck) {
        if (enableNotNullCheck) {
            if (paramCheck != null && paramCheck.required() && value.isEmpty()) {
                throw new BusinessException(paramCheck.description() + "不能为空!");
            }
        }
        if (enableLengthCheck) {
            if (paramCheck != null && paramCheck.maxLength() > 0 && value.length() > paramCheck.maxLength()) {
                throw new BusinessException(paramCheck.description() + "长度不能超过 " + paramCheck.maxLength());
            }
        }
    }

    private boolean isJavaBean(Class<?> clazz) {
        try {
            // 检查是否有无参构造函数
            Constructor<?> constructor = clazz.getConstructor();
            if (constructor == null) {
                return false;
            }

            // 检查是否有属性和对应的 getter/setter 方法
            BeanInfo beanInfo = Introspector.getBeanInfo(clazz);
            PropertyDescriptor[] propertyDescriptors = beanInfo.getPropertyDescriptors();
            return propertyDescriptors.length > 1; // 排除 class 属性
        } catch (Exception e) {
            return false;
        }
    }
}